/*
 * client_mgr.cpp
 *
 *  Created on: Aug 2, 2013
 *      Author: killerg
 */

#include "auth_deps.h"
#include "auth_mgr.h"
#include "auth.h"
#include "auth_cfg.h"

#include "share/util.h"
#include "share/console2.h"
#include "share/cfg_file.h"
#include "share/clock.h"


#include "share/cl_msg.pb.h"
#include "share/sl_msg.pb.h"


using namespace std;

void auth(const string &account, const string &mc, auth_mgr_t::auth_cb_t cb) {
	if (g_auth.authmgr->pending.size() > 1000) {
        cb(-1, "", "", "");
        return;
	}

	if (g_auth.authmgr->pending.count(account) > 0) {
        cb(-1, "", "", "");
        return;
    }

    g_auth.authmgr->pending.insert(account);

    g_auth.authmgr->get_account(
            account.c_str(),
            [mc, account, cb](db_error_t err, const auth_mgr_t::account_t &acc){
                g_auth.authmgr->pending.erase(account);
                Json::Value ret_data;
                ret_data["account"] = account;
                switch (err) {
                case DBE_Success:
                    cb(acc.playerid, account, mc, to_cstr(ret_data));
                    g_auth.authmgr->signin(mc);
                    break;
                case DBE_NoExist:
                    g_auth.authmgr->add_account(
                            account.c_str(),
                            "",
                            [mc, account, cb](db_error_t err, int32_t playerid){
                                Json::Value ret_data;
                                ret_data["account"] = account;
                                switch (err) {
                                case DBE_Success:
                                    cb(playerid, account, mc, to_cstr(ret_data));
                                    g_auth.authmgr->signin(mc);
                                    break;
                                case DBE_Exist:
                                    cb(-1, account, "", mc);
                                    break;
                                default:
                                    cb(-1, account, "", mc);
                                    break;
                                }
                            });
                    break;
                default:
                    cb(-1, account, "", "");
                    break;
                }
            });

}

/*
 * auth_data
 * {
 * 	session:xxxxx,
 *   mc:"xxxx",
 * 	uid:xxxxxx
 * }
 */
void auth_mi(const Json::Value &auth_data, auth_mgr_t::auth_cb_t cb) {
	static const char* appId = "23752";
	static const char* appKey = "71f76a0c-b11f-6807-16bb-5305f2d0685a";

    if (g_auth.authmgr->pending.size() >= 5000) {
        cb(-1, "", "", "");
        return;
    }

    if (!auth_data.isObject()) {
        cb(-1, "", "", "");
        return;
    }

    if (!auth_data["session"].isString() || !auth_data["uid"].isString() || !auth_data["mc"].isString()) {
        cb(-1, "", "", "");
        return;
    }

    string session = auth_data["session"].asCString();
    string uid = auth_data["uid"].asCString();
    string mc = auth_data["mc"].asCString();
    string param = fmt_cstr("appId=%s&session=%s&uid=%s", appId, session.c_str(), uid.c_str());
    string sign = Sha1(param.c_str(), appKey);
    string url = fmt_cstr("http://mis.migc.xiaomi.com/api/biz/service/verifySession.do?%s&signature=%s", param.c_str(), sign.c_str());
//    UTIL_LOG(I, "mi url:%s", url.c_str());

    mem_log("auth_mi start uid:%s url:%s", uid.c_str(), url.c_str());
    bool res = g_auth.authmgr->http.do_query(
            url.c_str(),
            NULL,
            [auth_data, mc, uid, cb](int code, const string &data){
                --g_auth.authmgr->httpop_num;
                mem_log("auth_mi finish uid:%s", uid.c_str());

                const Json::Value json = to_json(data);
                if (!json.isObject()) {
                	UTIL_LOG(E, "err http_req of auth_mi:%s", data.c_str());
                    cb(-1, "", "", "");
                    return;
                }

                switch (json["errcode"].asInt()) {
                case 200: {
                    string account = fmt_cstr("mi-%s", uid.c_str());
                    auth(account, mc, cb);
                    break;
                }
                default:
                    cb(-1, "", "", "");
                    break;
                }
            });
    if (res)
        ++g_auth.authmgr->httpop_num;

}


/*
 * auth_data
 * {
 *   mc:"xxxx",
 * 	sid:xxxx
 * }
 */void auth_uc(const Json::Value &auth_data, auth_mgr_t::auth_cb_t cb) {
//    static const char* uc_url = "http://sdk.test4.g.uc.cn/ss/";
    const char* uc_url = "http://sdk.g.uc.cn/ss/";
    if (g_cfg->Test)
        uc_url = "http://sdk.test4.g.uc.cn/ss/";

    static const char* uc_service = "ucid.user.sidInfo";
    static int channelId = 3;
    static int serverId = 0;
    static int cpId = 32838;
    static int gameId = 537117;
    static const char* apiKey = "52edb3cfe5104ed1d8d7b9cb2bcb0a90";

    if (g_auth.authmgr->pending.size() >= 5000) {
        cb(-1, "", "", "");
        return;
    }

    int serial = g_auth.clock->tt_now;

    if (!auth_data.isObject()) {
        cb(-1, "", "", "");
        return;
    }

    if (!auth_data["sid"].isString() || !auth_data["mc"].isString()) {
        cb(-1, "", "", "");
        return;
    }

    string sid = auth_data["sid"].asCString();
    string mc = auth_data["mc"].asCString();
    Json::Value body;
    body["id"] = serial;
    body["service"] = uc_service;

    Json::Value &data_json = body["data"];
    data_json["sid"] = sid;

    Json::Value &game_json = body["game"];
    game_json["cpId"] = cpId;
    game_json["gameId"] = gameId;
    game_json["channelId"] = channelId;
    game_json["serverId"] = serverId;

    body["sign"] = Md5(fmt_cstr("%dsid=%s%s", cpId, sid.c_str(), apiKey));

    mem_log("auth_uc start sid:%s url:%s", sid.c_str(), uc_url);
    bool res = g_auth.authmgr->http.do_query(
            uc_url,
            to_cstr(body),
            [sid, serial, mc, cb](int code, const string &data){
    			--g_auth.authmgr->httpop_num;
    			mem_log("auth_uc finish sid:%s", sid.c_str());

                if (CURLE_OK != code) {
                    cb(-1, "", "", "");
                    return;
                }


                const Json::Value res_json = to_json(data);
                if (!res_json.isObject()) {
                	UTIL_LOG(E, "err http_req of auth_uc:%s", data.c_str());
                    cb(-1, "", "", "");
                    return;
                }

                if (res_json["id"].asInt() != serial) {
                    cb(-1, "", "", "");
                    return;
                }

                const Json::Value &state_json = res_json["state"];
                if (1 != state_json["code"].asInt()) {
                    cb(-1, "", "", to_cstr(state_json));
                    return;
                }

                const Json::Value &date_json = res_json["data"];
                int ucid = date_json["ucid"].asInt();
                string account = fmt_cstr("uc-%d", ucid);
                auth(account, mc, cb);
            });
    if (res)
        ++g_auth.authmgr->httpop_num;
}

/*
 * auth_data
 * {
 * 	Uin:xxxxx,
 *   mc:"xxxx",
 * 	SessionId:xxxxxx
 * }
 */
void auth_91(const Json::Value &auth_data, auth_mgr_t::auth_cb_t cb) {
	static const int AppId = 110889;
	static const char* AppKey = "1c8f4d6c09134198a982c5a50f4f30ff61d08ec1dfa7a117";
    const static int Act = 4;
    const char* curl = "http://service.sj.91.com/usercenter/AP.aspx";

    if (!auth_data.isObject()) {
        cb(-1, "", "", "");
        return;
    }

    if (!auth_data["Uin"].isString() || !auth_data["SessionId"].isString() || !auth_data["mc"].isString()) {
        cb(-1, "", "", "");
        return;
    }

    const string Uin = auth_data["Uin"].asCString();
    const string SessionId = auth_data["SessionId"].asCString();
    const string mc = auth_data["mc"].asCString();

    const string Sign = Md5(fmt_cstr("%d%d%s%s%s", AppId, Act, Uin.c_str(), SessionId.c_str(), AppKey));

    const string url =
            fmt_cstr("%s?AppId=%d&Act=%d&Uin=%s&Sign=%s&SessionId=%s",
            		curl,
                    AppId,
                    Act,
                    Uin.c_str(),
                    Sign.c_str(),
                    SessionId.c_str());

    mem_log("auth_91 start Uin:%s url:%s", Uin.c_str(), url.c_str());
    bool res = g_auth.authmgr->http.do_query(
            url.c_str(),
            NULL,
            [cb, Uin, mc](int code, const string &data){
                --g_auth.authmgr->httpop_num;
                mem_log("auth_91 finish Uin:%s", Uin.c_str());

                if (CURLE_OK != code) {
                    cb(-1, "", "", "");
                    return;
                }

                Json::Value ret_json = to_json(data);
                if (!ret_json.isObject()) {
                	UTIL_LOG(E, "err http_req of auth_91:%s", data.c_str());
                    cb(-1, "", "", "");
                    return;
                }

                const string ErrorCode = ret_json["ErrorCode"].asCString();
                const string ErrorDesc = ret_json["ErrorDesc"].asCString();
                if (ErrorCode != "1") {
                    cb(-1, "", "", "");
                    return;
                }

                string account = fmt_cstr("91-%s", Uin.c_str());
                auth(account, mc, cb);
            });
    if (res) {
        ++g_auth.authmgr->httpop_num;
    }
}

/*
 * auth_data
 * {
 *   mc:"xxxx",
 * 	code:xxxxx
 * }
 */
void auth_360(const Json::Value &auth_data, auth_mgr_t::auth_cb_t cb) {
	static const char* access_token_url = "https://openapi.360.cn/oauth2/access_token";
	static const char* me_url = "https://openapi.360.cn/user/me.json";
    static const int app_id = 201306956;
    static const char* app_key = "fee302ddf2f1bf1be029e0581771c4b1";
    static const char* app_secret = "08aef7138646b3846536755d14665b58";

    if (!auth_data.isObject()) {
        cb(-1, "", "", "");
        return;
    }

    if (!auth_data["code"].isString() || !auth_data["mc"].isString()) {
    	cb(-1, "", "", "");
    	return;
    }

    string code = auth_data["code"].asCString();
    string mc = auth_data["mc"].asCString();

    string url = fmt_cstr(
    		"%s?grant_type=authorization_code&code=%s&client_id=%s&client_secret=%s&redirect_uri=oob",
    		access_token_url,
    		code.c_str(),
    		app_key,
    		app_secret
    		);

    mem_log("auth_360 start code:%s url:%s", code.c_str(), url.c_str());
    bool res = g_auth.authmgr->http.do_query(
    		url.c_str(),
    		NULL,
    		[mc, cb, code](int errcode, const string &ret){
				--g_auth.authmgr->httpop_num;
			    mem_log("auth_360 finish code:%s", code.c_str());

			    if (CURLE_OK != errcode) {
					cb(-1, "", "", "");
					return;
				}

				const Json::Value jRet = to_json(ret);
                if (!jRet.isObject()) {
                	UTIL_LOG(E, "err http_res of auth_360:%s", ret.c_str());
                    cb(-1, "", "", "");
                    return;
                }

				if (jRet["error_code"].isString()) {
					UTIL_LOG(E, "ret:%s", to_cstr(jRet));
					cb(-1, "", "", "");
					return;
				}

				if (!jRet["access_token"].isString()) {
					UTIL_LOG(E, "ret:%s", to_cstr(jRet));
					cb(-1, "", "", "");
					return;
				}

				string access_token = jRet["access_token"].asCString();
				if (access_token.empty()) {
					cb(-1, "", "", "");
					return;
				}

			    string url = fmt_cstr(
			    		"%s?access_token=%s&fields=id",
			    		me_url,
			    		access_token.c_str()
			    		);

			    mem_log("auth_360 start access_token:%s url:%s", access_token.c_str(), url.c_str());
				bool res = g_auth.authmgr->http.do_query(
						url.c_str(),
						NULL,
						[mc, access_token, cb](int errcode, const string &ret){
							--g_auth.authmgr->httpop_num;
						    mem_log("auth_360 finish access_token:%s", access_token.c_str());

						    if (CURLE_OK != errcode) {
								cb(-1, "", "", "");
								return;
							}

							const Json::Value jRet = to_json(ret);
			                if (!jRet.isObject()) {
			                	UTIL_LOG(E, "err http_res of auth_360:%s", ret.c_str());
			                    cb(-1, "", "", "");
			                    return;
			                }

							if (jRet["error_code"].isString()) {
								UTIL_LOG(E, "ret:%s", to_cstr(jRet));
								cb(-1, "", "", "");
								return;
							}

							string id = jRet["id"].asCString();
							if (id.empty()) {
								cb(-1, "", "", "");
								return;
							}

							string account = fmt_cstr("360-%s", id.c_str());
			                auth(
			                	account,
			                	mc,
								[cb, access_token](int32_t playerid, const std::string &account, const std::string &mc, const std::string &data){
			                		if (playerid >= 0) {
			                			Json::Value json = to_json(data);
			                			json["access_token"] = access_token;
			                			cb(playerid, account, mc, to_str(json));
			                		} else {
			                			cb(playerid, account, mc, data);
			                		}
								});
						});
				if (res)
					++g_auth.authmgr->httpop_num;

    		});
    if (res)
		++g_auth.authmgr->httpop_num;

}
/*
 * auth_data
 * {
 *   account:"account",
 *   passwd:123456,
 *   step:"auth",
 *   mc:"xxxx",
 * } step: auth, reg
 */
//

// ret {error:"success", step:"auth"} error: success, exist, needreg, passwderr, temperr
void auth_au(const Json::Value &auth_data, auth_mgr_t::auth_cb_t cb) {
#define AUTH_ACCOUNT "account"
#define AUTH_PASSWD "passwd"
#define AUTH_STEP "step"
#define AUTH_ERROR "error"
#define AUTH_STEP_AUTH "auth"
#define AUTH_STEP_REG "reg"
#define AUTH_ERR_SUCCESS "success"
#define AUTH_ERR_EXIST "exist"
#define AUTH_ERR_PASSWD "passwd"
#define AUTH_ERR_NEEDREG "needreg"
#define AUTH_ERR_OTHER "other"

#define DB_ACCOUNT "account"
#define DB_PASSWD "passwd"
#define DB_PLAYERID "playerid"

    if (!auth_data.isObject()) {
        cb(-1, "", "", "");
        return;
    }

    if (!auth_data[AUTH_ACCOUNT].isString() ||
        !auth_data[AUTH_PASSWD].isString() ||
        !auth_data[AUTH_STEP].isString()
        ) {
        cb(-1, "", "", "");
        return;
    }

    string account = auth_data[AUTH_ACCOUNT].asCString();
    string passwd = auth_data[AUTH_PASSWD].asCString();
    string step = auth_data[AUTH_STEP].asCString();

    account = fmt_cstr("au-%s", account.c_str());
    string mc = account;

    if (g_auth.authmgr->pending.count(account) > 0) {
        cb(-1, "", "", "");
        return;
    }

    g_auth.authmgr->pending.insert(account);

    if (step == AUTH_STEP_AUTH) {
        g_auth.authmgr->get_account(
                account.c_str(),
                [mc, cb, account, passwd](db_error_t err, const auth_mgr_t::account_t &acc){
                    string strerr = AUTH_ERR_SUCCESS;
                    switch (err) {
                    case DBE_Success:
                        if (acc.passwd != passwd)
                            strerr = AUTH_ERR_PASSWD;
                        else
                        	g_auth.authmgr->signin(mc);
                        break;
                    case DBE_NoExist:
                        strerr = AUTH_ERR_NEEDREG;
                        break;
                    default:
                        strerr = AUTH_ERR_OTHER;
                        break;
                    }

                    Json::Value ret_json;
                    ret_json[AUTH_ERROR] = strerr;
                    ret_json[AUTH_STEP] = AUTH_STEP_AUTH;

                    cb(acc.playerid, account, mc, to_str(ret_json));
                    g_auth.authmgr->pending.erase(account);
                });
    } else if (step == AUTH_STEP_REG) {
        g_auth.authmgr->add_account(
                account.c_str(),
                passwd.c_str(),
                [mc, cb, account](db_error_t err, int32_t playerid){
                    string strerr = AUTH_ERR_SUCCESS;
                    switch (err) {
                    case DBE_Success:
                        break;
                    case DBE_Exist:
                        strerr = AUTH_ERR_EXIST;
                        break;
                    default:
                        strerr = AUTH_ERR_OTHER;
                        break;
                    }

                    Json::Value ret_json;
                    ret_json[AUTH_ERROR] = strerr;
                    ret_json[AUTH_STEP] = AUTH_STEP_REG;

                    cb(playerid, account, mc, to_str(ret_json));
                    g_auth.authmgr->pending.erase(account);
                });
    } else {
        cb(-1, "", "", "");
        g_auth.authmgr->pending.erase(account);
        return;
    }
}



bool auth_mgr_t::init() {

    funs[co::EPI_au] = auth_au;
    funs[co::EPI_91] = auth_91;
    funs[co::EPI_uc] = auth_uc;
    funs[co::EPI_mi] = auth_mi;
    funs[co::EPI_360] = auth_360;

    _inited = false;

    bool ok = true;

    ok = db.init(g_auth.cfg->DbHost, "", "", g_auth.cfg->DbBucket);
    if (!ok) {
        UTIL_LOG(E, "db init err");
        return false;
    }

    ok = db.get("_auth_maxid", [this, &ok](db_error_t error, const Json::Value &value){
        if (DBE_Success == error) {
            maxid = value["maxid"].asInt();
        } else {
            maxid = 0;
        }
    });
    if (!ok) {
        UTIL_LOG(E, "auth_mgr_t::init db get err");
        return false;
    }
    db.wait();

    db.get("_auth_validid", [this](db_error_t error, const Json::Value &value){
        if (DBE_Success == error) {
            const Json::Value &validid = value["validid"];
            for (auto itr = validid.begin(); itr != validid.end(); ++itr)
                valid_id.push_back((*itr).asInt());
        }
    });
    if (!ok) {
        UTIL_LOG(E, "auth_mgr_t::init db get err");
        return false;
    }
    db.wait();

    if (!http.init()) {
        UTIL_LOG(E, "auth_mgr_t::init http init err");
        return false;
    }

    _inited = true;
    return true;
}

void auth_mgr_t::destroy() {
    if (!_inited)
        return;

    http.destroy();

    Json::Value json;
    Json::Value &validid = json["validid"];
    while (!valid_id.empty()) {
        validid.append(valid_id.front());
        valid_id.pop_front();
    }

    db.set("_auth_validid", json, [](db_error_t error){
        if (DBE_Success != error) {
            UTIL_LOG(E, "couldn't save validid %s", db_strerror(error));
        }
    });
    db.wait();

    db.destroy();

    cache.for_each([](const string &key, cache_item_t* &value){
    	safe_del(value);
    });
    cache.clear();

    signin_cache.for_each([](const string &key, signin_cache_t* &value){
    	safe_del(value);
    });
    signin_cache.clear();
}

void auth_mgr_t::update() {
    db.update();
    http.update();

    if (cache.size() > g_cfg->MaxCachedAccount) {
        struct comp {
            bool operator() (cache_item_t* lhs, cache_item_t* rhs) {
                return lhs->hit_count > rhs->hit_count;
            }
        };

        priority_queue<cache_item_t*, vector<cache_item_t*>, comp > gc_queue;

        for (auto itr = cache.begin(); itr != cache.end(); ++itr) {
            gc_queue.push(itr->second);
        }

        int remain = g_cfg->MaxCachedAccount * 0.8f;
        while (!gc_queue.empty() && cache.size() > remain) {
            auto cached = gc_queue.top();
            gc_queue.pop();
            cache.erase(cached->account);
            delete cached;
        }
    }
}

void auth_mgr_t::get_account(
        const char* account,
        std::function<void(db_error_t, const account_t&)> cb) {

    cache_item_t* cached = cache.get(account);
    if (NULL != cached) {
        account_t acc;
        acc.passwd = cached->passwd;
        acc.playerid = cached->playerid;
        acc.account = cached->account;
        cb(DBE_Success, acc);
        ++cached->hit_count;

        return;
    }

    bool ret = db.get(
            fmt_cstr("account:%s", account),
            [this, cb](db_error_t err, const Json::Value &value){
                account_t acc;
                acc.account = value.get("account", "").asCString();
                acc.playerid = value.get("playerid", -1).asInt();
                acc.passwd = value.get("passwd", "").asCString();
                cb(err, acc);

                cache_item_t* cached = cache.get(acc.account);
                if (NULL == cached) {
                    cached = new cache_item_t;
                    cached->account = acc.account;
                    cached->passwd = acc.passwd;
                    cached->playerid = acc.playerid;
                    cache.set(acc.account, cached);
                }
                ++cached->hit_count;
            });

    if (!ret) {
        account_t acc;
        acc.playerid = -1;
        acc.account = account;
        cb(DBE_TryMoreLater, acc);
    }
}

void auth_mgr_t::add_account(
        const char* account,
        const char* passwd,
        std::function<void(db_error_t, int32_t)> cb) {

    int32_t playerid = _alloc_id();

    Json::Value acc;
    acc["account"] = account;
    acc["playerid"] = playerid;
    acc["passwd"] = passwd;

    account_t accs;
    accs.account = account;
    accs.playerid = playerid;
    accs.passwd = passwd;


    string key = fmt_cstr("account:%s", account);
    bool ret = db.add(key.c_str(), acc, [accs, this, cb, playerid](db_error_t err){
        switch (err) {
        case DBE_Success: {
            cache_item_t* cached = cache.get(accs.account);
            if (NULL == cached) {
                cached = new cache_item_t;
                cached->account = accs.account;
                cached->passwd = accs.passwd;
                cached->playerid = accs.playerid;
                cached->hit_count = 0;
                cache.set(accs.account, cached);
            }
            cb(err, playerid);
        }
            break;
        default:
            cb(err, -1);
            _return_id(playerid);
            break;
        }
    });

    if (!ret)
        cb(DBE_TryMoreLater, -1);
}

void auth_mgr_t::_save_maxid() {
    Json::Value json;
    json["maxid"] = maxid;
    auto idtosave = maxid;
    db.set("_auth_maxid", json, [idtosave](db_error_t error){
        if (DBE_Success != error) {
        	UTIL_LOG(E, "could not save maxid %d %s", idtosave, db_strerror(error));
        }
    });
}
void auth_mgr_t::_return_id(int32_t id) {
    valid_id.push_back(id);
}

int32_t auth_mgr_t::_alloc_id() {
    int32_t newid = -1;
    if (valid_id.empty()) {
        newid = maxid++;
        _save_maxid();
    } else {
        newid = valid_id.front();
        valid_id.pop_front();
    }
    return newid;
}

void signin_db(auth_mgr_t::signin_cache_t* cache) {
	cache->last_signin = g_clock->tt_now;

	Json::Value json;
	json["objtype"] = "signin";
	json["mc"] = cache->mc;
	json["create"] = Json::Int64(cache->create);
	json["last_signin"] = Json::Int64(cache->last_signin);
	const string mc = cache->mc;
	g_auth.authmgr->db.set(fmt_cstr("signin:%s",cache->mc.c_str()), json, [mc](db_error_t err){
		if (err != DBE_Success) {
			UTIL_LOG(E, "save db signin:%s err:%s", mc.c_str(), db_strerror(err));
		}
	});
	g_auth.db_log->add(fmt_cstr("signin:%s:%lld", cache->mc.c_str(), g_clock->tt_now), json, [mc](db_error_t err){
		if (err != DBE_Success) {
			UTIL_LOG(E, "save log signin:%s err:%s", mc.c_str(), db_strerror(err));
		}
	});

}

void auth_mgr_t::signin(const std::string &mc) {
	auto cache = signin_cache.get(mc);
	if (NULL != cache) {
		if (cache->create <= 0) {
			return;
		}
		tm last_signin_tm;
		tm now_tm;
		last_signin_tm = *localtime(&cache->last_signin);
		now_tm = *localtime(&g_clock->tt_now);

		if (last_signin_tm.tm_yday != now_tm.tm_yday) {
			signin_db(cache);
		}
		return;
	}

	cache = new signin_cache_t;
	cache->mc = mc;
	cache->create = -1;
	cache->last_signin = -1;

	bool ok = db.get(fmt_cstr("signin:%s",mc.c_str()), [mc](db_error_t err, const Json::Value &value){
		auto cache = g_auth.authmgr->signin_cache.get(mc);
		if (NULL == cache)
			return;

		switch (err) {
		case DBE_Success:
		{
    		cache->create = value["create"].asInt64();
    		cache->last_signin = value["last_signin"].asInt64();

    		tm last_signin_tm;
    		tm now_tm;
    		last_signin_tm = *localtime(&cache->last_signin);
    		now_tm = *localtime(&g_clock->tt_now);

    		if (last_signin_tm.tm_yday != now_tm.tm_yday) {
    			signin_db(cache);
    		}

		}
			break;
		case DBE_NoExist:
		{
			cache->create = g_clock->tt_now;
			signin_db(cache);
		}
			break;
		default:
			g_auth.authmgr->signin_cache.erase(cache->mc);
			safe_del(cache);
			break;
		}
	});
	if (ok) {
		signin_cache.set(cache->mc, cache);
	} else {
		delete cache;
	}
}

